package com.weilive.core.utils;

import java.util.HashMap;

public class SensitiveWordUtils {

	/**
	 * 节点 
	 */
	public static class Node {
		public final int deep;	// 深度
		public String word = null;	// 敏感词
		public HashMap<Character, Node> nodes = new HashMap<Character, Node>();	// 所有子节点
		
		public Node(int deep) { this.deep = deep; }
	}
	
	// 根节点
	private Node root = new Node(0); 
	
	/**
	 * 添加包含‘*’规则的敏感词
	 * @param word 敏感词
	 */
	public void addStarSensitiveWord(String word) {
		if (word == null || word.length() == 0) return;
		char first = word.charAt(0);
		if (first != '*' && first != ' ') {
			word = ' ' + word;
		} else if (first == '*'){
			word = word.substring(1);
		}
		if (word.length() == 0) return;
		char last = word.charAt(word.length() - 1);
		if (last != '*' && last != ' ') {
			word = word + ' ';
		} else if (last == '*'){
			word = word.substring(0, word.length() - 1);
		}
		if (word.length() == 0) return;
		addSensitiveWord(word);
	}
	
	/**
	 * 添加敏感词
	 * @param word 敏感词
	 */
	public void addSensitiveWord(String word) {
		if (word == null || word.length() == 0) return;
		char[] chars = word.toCharArray();
		Node curr = root;
		for (int i = 0; i < chars.length; i ++) {
			Node next = curr.nodes.get(chars[i]);
			if (next == null) {
				next = new Node(i+1);
				curr.nodes.put(chars[i], next);
			}
			curr = next;
			if (i == chars.length - 1) {
				curr.word = word;
			}
		}
	}
	
	/**
	 * 判断单词是否包含敏感词
	 * @param text 文本
	 * @return true则包含，false则不包含
	 */
	public boolean containsSensitiveWorld(String text) {
		if (text == null || text.length() == 0) return false;
		char[] chars = text.toCharArray();
		for (int i = 0; i < chars.length; i ++) {
			if (hintFirst(chars, i) != null) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 替换文本中的敏感词
	 * @param text 文本
	 * @param replace 需要替换的字符
	 * @return 替换后的文本
	 */
	public String replaceSensitiveWorld(String text, char replace) {
		if (text == null || text.length() == 0) return text;
		boolean hint = false;
		char[] chars = text.toCharArray();
		for (int i = 0; i < chars.length; i ++) {
			Node node = hintLast(chars, i);
			if (node != null) {
				hint = true;
				for (int j = 0; j < node.deep; j ++) {
					if (chars[i+j] != ' ') {
						chars[i+j] = replace;
					}
				}
				i += node.deep - 1;
			}
		}
		return hint ? new String(chars) : text;
	}
	
	/**
	 * 私有函数：以当前offset为头部，找到第一个命中的敏感词(即最短的敏感词)
	 */
	private Node hintFirst(char[] chars, int offset) {
		Node curr = root;
		for (int i = offset; i < chars.length; i ++) {
			Node next = curr.nodes.get(chars[i]);
			if (next == null) {
				return null;
			}
			if (next.word != null) {
				return next;
			}
			curr = next;
		}
		return null;
	}
	
	/**
	 * 私有函数：以当前offset为头部，找到最后一个命中的敏感词(即最长的敏感词)
	 */
	private Node hintLast(char[] chars, int offset) {
		Node ret = null;
		Node curr = root;
		for (int i = offset; i < chars.length; i ++) {
			Node next = curr.nodes.get(chars[i]);
			if (next == null) {
				break;
			}
			if (next.word != null) {
				ret = next;
			}
			curr = next;
		}
		return ret;
	}
	
	/**
	 * 测试用例 
	 */
	public static void main(String[] args) throws Exception {
		SensitiveWordUtils util = new SensitiveWordUtils();
		util.addSensitiveWord("0");
		util.addSensitiveWord("1");
		util.addSensitiveWord("12");
		util.addSensitiveWord("123");
		util.addSensitiveWord("234");
		util.addSensitiveWord("34");
		
		util.addStarSensitiveWord("*fuck*");
		util.addStarSensitiveWord("*haha");
		util.addStarSensitiveWord("kk*");
		util.addStarSensitiveWord("bitch");
		
		System.out.println(util.containsSensitiveWorld("4x243"));
		System.out.println(util.replaceSensitiveWorld("1-2345", '?'));
		
		System.out.println(util.containsSensitiveWorld("youfuck bitch abitch"));
		System.out.println(util.replaceSensitiveWorld("youfuck bitch abitch kkx xkk uuhaha hahaxxx", '?'));
	}
}
